package com.duowan.cms.action;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.duowan.cms.common.domain.Page;
import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.dto.user.PowerInfo;
import com.duowan.cms.dto.user.UserInfo;
import com.duowan.cms.dto.user.UserPowerInfo;
import com.duowan.cms.dto.user.UserPowerSearchCriteria;
import com.duowan.cms.dto.user.UserRole;
import com.duowan.cms.dto.user.UserSearchCriteria;
import com.duowan.cms.service.channel.ChannelService;
import com.duowan.cms.service.user.PowerService;
import com.duowan.cms.service.user.UserService;
import com.duowan.cms.util.RequestUtil;

@Controller
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private PowerService powerService;
    @Autowired
    private ChannelService channelService;

    private static Logger logger = Logger.getLogger(UserController.class);

    /**
     * 用户列表:显示系统用户
     */
    @RequestMapping(value = "/user/userList", method = RequestMethod.GET)
    public String userList(HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.getSession().removeAttribute("channelInfo");// 清除频道信息
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        if (!userInfo.isAdmin()) {// 非管理员无法进入
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有[系统管理员]权限", "UTF-8");
        }
        configUserList(request);
        return "/user/user_list";
    }

    private void configUserList(HttpServletRequest request) {
        String searchkey = request.getParameter("searchkey");
        String pageNo = request.getParameter("pageNo");
        
        // 设置列表信息
        UserSearchCriteria searchCriteria = new UserSearchCriteria();
        
        if(!StringUtil.isEmpty(searchkey)){
            searchCriteria.setUserId(searchkey);
        }
        if (!StringUtil.isEmpty(pageNo)) {
            searchCriteria.setPageNo(Integer.parseInt(pageNo));
        }
        Page<UserInfo> userInfoPage = userService.pageSearch(searchCriteria);
        request.setAttribute("userInfoPage", userInfoPage);

        // 设置"上一个请求的查询条件"到页面
        //将searchkey中的特殊字符替换，防止存在跨站脚本攻击安全漏洞
        searchkey = StringUtil.clearHTML(searchkey);
        request.setAttribute("searchkey", "null".equals(searchkey) ? "" : searchkey);
        request.setAttribute("queryStr", "&searchkey=" + searchkey);

    }

    /**
     * 用户管理:管理某频道下的所有用户
     */
    @RequestMapping(value = "/user/userManage", method = RequestMethod.GET)
    public String userManage(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("searchCriteria") UserPowerSearchCriteria searchCriteria) throws IOException {

        String channelId = searchCriteria.getChannelId();

        Page<UserPowerInfo> userPowerInfoPage = userService.pageSearch(searchCriteria);
        request.setAttribute("userPowerInfoPage", userPowerInfoPage);
        request.setAttribute("userId", searchCriteria.getUserId());
        request.setAttribute("channelId", channelId);
        // 取出自己的权限
        request.setAttribute("curPowerInfo", getCurrentPowerInfo(request, channelId));
        return "/user/user_manage";
    }

    private UserPowerInfo getCurrentPowerInfo(HttpServletRequest request, String channelId) {

        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        return userService.getByUserIdAndChannelId(userInfo.getUserId(), channelId);
    }

    /**
     * 检查用户是否已经存在
     */
    @RequestMapping(value = "/user/checkUserId", method = RequestMethod.GET)
    public void checkUserId(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        String channelId = request.getParameter("channelId");
        if (!StringUtil.isEmpty(channelId)) {
            logger.info("开始检查用户[" + userId + "]是否存在于[" + channelId + "]频道");
            UserPowerInfo userPowerInfo = userService.getByUserIdAndChannelId(userId, channelId);
            if (userPowerInfo != null) {
                logger.info("用户[" + userId + "]已经存在于[" + channelId + "]频道");
                response.getWriter().write("exist");
                return;
            }
            logger.info("用户[" + userId + "]不存在于[" + channelId + "]频道,开始检查系统是否存在[" + userId + "]用户");

        }
        if (userService.checkUserExist(userId)) {
            logger.info("用户[" + userId + "]已经存在于系统，可以把它加入[" + channelId + "]频道");
            response.getWriter().write("addUserToChannel");
        } else {
            logger.info("用户[" + userId + "]不存在于系统，准备添加用户[" + userId + "]到系统，并加入[" + channelId + "]频道");
            response.getWriter().write("addUser");
        }

    }

    /**
     * 导航到"用户个人信息"页面
     */
    @RequestMapping(value = "/user/toEditUserPrivateInfoPage", method = RequestMethod.GET)
    public String toEditUserPrivateInfoPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        return "user/personal_info";// "/user/user_private_info";
    }

    @RequestMapping(value = "/user/updatePersonalName", method = RequestMethod.POST)
    public String updatePersonalName(HttpServletRequest request, HttpServletResponse response) throws IOException, BaseCheckedException {

        String newName = request.getParameter("userId");
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");

        if (validateNewName(newName) && !userInfo.getUserId().equals(newName)) {
            userService.updateUserName(userInfo.getUserId(), newName.trim());
            // 更新session信息
            UserInfo newUserInfo = userService.getById(newName.trim());
            request.getSession().setAttribute("userInfo", newUserInfo);
        }
        return "redirect:/index.do";
    }

    private boolean validateNewName(String newName) {
        if (StringUtil.isEmpty(newName))
            return false;
        Pattern p = Pattern.compile("[\\u4E00-\\u9FFF]{1,4}");
        Matcher m = p.matcher(newName);
        return m.matches() && null == userService.getById(newName);
    }

    @RequestMapping(value = "/user/checkPersonalPassword", method = RequestMethod.POST)
    public void checkPersonalPassword(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String password = request.getParameter("password");
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");

        if (null != userService.getByUserIdAndPassword(userInfo.getUserId(), password)) {
            response.getWriter().write("success");
        } else {
            response.getWriter().write("fail");
        }
    }

    @RequestMapping(value = "/user/updatePersonalMail", method = RequestMethod.POST)
    public void updatePersonalMail(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String mail = request.getParameter("mail");

        if (!StringUtil.isEmpty(mail) && mail.indexOf("@") > 0) {
            UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
            userInfo.setMail(mail.trim());
            userInfo.setLastModifyTime(new Date());
            userService.updateUser(userInfo);
            response.getWriter().write("success");
        } else {
            response.getWriter().write("fail");
        }
    }

    @RequestMapping(value = "/user/updatePersonalPassword", method = RequestMethod.POST)
    public void updatePersonalPassword(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String oldPassword = request.getParameter("oldpassword");
        String newPassword = request.getParameter("newpassword");
        String rePassword = request.getParameter("repassword");

        if (!newPassword.equals(rePassword)) {
            response.getWriter().write("two password not the same!");
            return;
        }

        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        if (null == userService.getByUserIdAndPassword(userInfo.getUserId(), oldPassword)) {
            response.getWriter().write("the old password is not right!");
            return;
        }
        // update user password
        userInfo.setPassword(newPassword);
        userInfo.setLastModifyTime(new Date());
        userService.updateUser(userInfo);
        // the password is not allowed in the user session
        response.getWriter().write("success");
        // 让用户重新登录
        request.getSession().removeAttribute("userInfo");
    }
    
    @RequestMapping(value = "/user/bindingUdb", method = RequestMethod.POST)
    public void bindingUdb(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String passport = request.getParameter("passport");

        if (StringUtil.isEmpty(passport) || !passport.startsWith("dw_")) {
            response.getWriter().write("通行证格式必须以'dw_'开头");
            return;
        }

        try{
            UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
            // update user password
            userInfo.setUdbName(passport);
            userInfo.setLastModifyTime(new Date());
            userService.updateUser(userInfo);
            // the password is not allowed in the user session
            response.getWriter().write("success");
        }catch(Exception e){
            response.getWriter().write("fail");
        }
        
    }

    /**
     * 更新"用户个人信息"
     */
    @RequestMapping(value = "/user/editUserPrivateInfo", method = RequestMethod.POST)
    public void editUserPrivateInfo(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("userInfo") UserInfo editedUserInfo) throws IOException,
            BaseCheckedException {
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        userInfo.setMail(editedUserInfo.getMail());
        userInfo.setLastModifyTime(new Date());
        if (!StringUtil.isEmpty(editedUserInfo.getPassword())) {
            userInfo.setPassword(editedUserInfo.getPassword());
        }
        userService.updateUser(userInfo);

        // 更新用户名
        if (!userInfo.getUserId().equals(editedUserInfo.getUserId())) {
            userService.updateUserName(userInfo.getUserId(), editedUserInfo.getUserId());
        }

        // 更新session信息
        UserInfo newUserInfo = userService.getById(editedUserInfo.getUserId());
        request.getSession().setAttribute("userInfo", newUserInfo);

        response.getWriter().write("success");
        // return "redirect:/user/toEditUserPrivateInfoPage.do";
    }

    @RequestMapping(value = "/user/toEditUserPage", method = RequestMethod.GET)
    public String toEditUserPage(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String type = request.getParameter("type");
        String channelId = request.getParameter("channelId");

        if (!"add".equals(type)) {
            String userId = request.getParameter("userId");
            UserPowerInfo userPowerInfo = userService.getByUserIdAndChannelId(userId, channelId);
            // 校验权限
            UserPowerInfo curPowerInfo = getCurrentPowerInfo(request, channelId);
            if (curPowerInfo.getUserRole().getPowerValue() <= userPowerInfo.getUserRole().getPowerValue()) {
                return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有修改[" + userPowerInfo.getUserRole().getDisplay() + "角色]权限", "UTF-8");
            }

            UserInfo userInfo = userService.getById(userId);
            request.setAttribute("userInfo", userInfo);
            request.setAttribute("userPowerInfo", userPowerInfo);
        }

        List<PowerInfo> allPowerInfoList = powerService.getAll();

        request.setAttribute("allPowerInfoList", allPowerInfoList);
        request.setAttribute("channelId", channelId);
        request.setAttribute("type", type);// 表示添加用户
        return "/user/user_edit";
    }

    @RequestMapping(value = "/user/updateUserToChannel", method = RequestMethod.POST)
    public String updateUserToChannel(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("userInfo") UserInfo userInfo) throws IOException,
            BaseCheckedException {
        String type = request.getParameter("type");
        UserPowerInfo userPowerInfo = this.bindUserPowerInfo(request);
        this.bindUserInfo(request, userInfo);
        if ("add".equals(type)) {
            userService.addUserPower(userPowerInfo);
        } else {
            userService.updateUserPower(userPowerInfo);
        }
        return "redirect:/user/userManage.do?channelId=" + userPowerInfo.getChannelId();
    }

    /**
     * 
     */
    @RequestMapping(value = "/user/updateUser", method = RequestMethod.POST)
    public String updateUser(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("userInfo") UserInfo userInfo) throws IOException, BaseCheckedException {
        String type = request.getParameter("type");
        UserPowerInfo userPowerInfo = this.bindUserPowerInfo(request);
        this.bindUserInfo(request, userInfo);

        if ("add".equals(type)) {
            userService.addUser(userInfo, userPowerInfo);
        } else {
            userService.updateUser(userInfo, userPowerInfo);
        }
        return "redirect:/user/userManage.do?channelId=" + userPowerInfo.getChannelId();
    }

    /**
     * 绑定用户权限信息
     * @param request
     */
    private UserPowerInfo bindUserPowerInfo(HttpServletRequest request) {
        String channelId = request.getParameter("channelId");
        String userId = request.getParameter("userId");
        String selectPower = request.getParameter("selectPower");
        String[] powerArr = selectPower.split(",");
        List<PowerInfo> ownPowers = new ArrayList<PowerInfo>();
        for (int i = 0; i < powerArr.length; i++) {
            ownPowers.add(new PowerInfo(powerArr[i], ""));
        }
        UserPowerInfo userPowerInfo = new UserPowerInfo();
        userPowerInfo.setUserId(userId);
        // 设置添加新用户的管理员id
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        userPowerInfo.setAdminId(userInfo.getUserId());
        userPowerInfo.setLastModifyTime(new Date());
        userPowerInfo.setOwnPowers(ownPowers);
        userPowerInfo.setUserRole(UserRole.getInstance(request.getParameter("role")));
        ChannelInfo channelInfo = channelService.getById(channelId);
        userPowerInfo.setChannelInfo(channelInfo);
        return userPowerInfo;
    }

    /**
     * 更新用户信息
     * @param request
     * @param userInfo
     */
    private UserInfo bindUserInfo(HttpServletRequest request, UserInfo userInfo) {
        userInfo.setProxyIp(RequestUtil.getProxyIp(request));
        userInfo.setUserIp(RequestUtil.getUserIp(request));
        return userInfo;
    }

    /**
     * 删除某频道下的用户
     */
    @RequestMapping(value = "/user/deletePower", method = RequestMethod.GET)
    public String deletePower(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        String channelId = request.getParameter("channelId");

        UserPowerInfo userPowerInfo = userService.getByUserIdAndChannelId(userId, channelId);
        // 校验权限
        UserPowerInfo curPowerInfo = getCurrentPowerInfo(request, channelId);
        if (curPowerInfo.getUserRole().getPowerValue() <= userPowerInfo.getUserRole().getPowerValue()) {
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有删除[" + userPowerInfo.getUserRole().getDisplay() + "角色]权限", "UTF-8");
        }

        userService.deletePower(userId, channelId);
        return "redirect:/user/userManage.do?channelId=" + channelId;
    }

    /**
     * 删除某个系统用户并删除它在所有频道的权限
     */
    @RequestMapping(value = "/user/deleteUser", method = RequestMethod.GET)
    public String deleteUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        if (!hasEnoughPower(request, userId))
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有删除[" + userId + "]权限", "UTF-8");
        userService.deleteUser(userId);
        return "redirect:/user/userList.do";
    }

    private boolean hasEnoughPower(HttpServletRequest request, String userId) {
        UserInfo curUser = (UserInfo) request.getSession().getAttribute("userInfo");
        // 自己修改自己，有权限
        if (curUser.getUserId().equals(userId))
            return true;
        // 非管理员，无权限
        if (!curUser.isAdmin())
            return false;
        UserInfo opeUser = userService.getById(userId);
        // 查无此人或此人为管理员，无权限
        if (opeUser == null || opeUser.isAdmin())
            return false;
        return true;
    }

    @RequestMapping(value = "/user/unFreeze", method = RequestMethod.GET)
    public String unFreeze(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        if (!hasEnoughPower(request, userId))
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有解冻[" + userId + "]权限", "UTF-8");
        userService.unFreeze(userId);
        return "redirect:/user/userList.do";
    }

    @RequestMapping(value = "/user/freeze", method = RequestMethod.GET)
    public String freeze(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        if (!hasEnoughPower(request, userId))
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有冻结[" + userId + "]权限", "UTF-8");
        userService.freeze(userId);
        return "redirect:/user/userList.do";
    }

    @RequestMapping(value = "/user/updateEmail", method = RequestMethod.GET)
    public String updateEmail(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");
        String email = request.getParameter("email");
        userService.updateEmail(userId, email);
        return "redirect:/user/";
    }

    @RequestMapping(value = "/user/updatePassword", method = RequestMethod.GET)
    public String updatePassword(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // TODO hjy 由于新的发布器可能接入UDB，原发布器更新密码的方式可能不再使用了。具体的实现方法待定。
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");
        userService.updatePassword(userId, password);
        return "user_list";
    }

    @RequestMapping(value = "/user/resetPassword", method = RequestMethod.POST)
    public void resetPassword(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userId = request.getParameter("userId");

        if (StringUtil.isEmpty(userId) || !hasEnoughPower(request, userId)) {
            response.getWriter().write("你没有权限重置" + userId + "密码");
            return;
        }
        String mail = request.getParameter("mail");

        UserInfo userInfo = userService.getById(userId);
        String oldMail = userInfo.getMail();

        if ((StringUtil.isEmpty(mail) || mail.indexOf("@") < 0)) {
            if ((StringUtil.isEmpty(oldMail) || oldMail.indexOf("@") < 0)) {
                response.getWriter().write("邮箱不符合规范!重置密码失败");
                return;
            } else {
                logger.warn("重置密码：输入邮箱为：" + mail + "不合法,将采用旧邮箱：" + oldMail);
                mail = oldMail;
            }
        }
        if (!mail.equals(oldMail)) {
            logger.warn("重置密码：用户的mail为：" + oldMail + ", 却要求发送到：" + mail);
        }

        String password = StringUtil.getRandomStr(15);
        // 修改密码
        userInfo.setPassword(password);
        userInfo.setLastModifyTime(new Date());
        userService.updateUser(userInfo);
        // 发送mail
        String title = "发布系统重设密码通知";
        String content = userId + ",您好:<br />您的新密码为：" + password;
        try {
            userService.sendMessageToMail(mail, title, content);
            response.getWriter().write("success");
        } catch (Exception e) {
            logger.error("密码修改后，邮件：" + mail + "发送不成功", e);
            response.getWriter().write("fail");
        }

    }

    @RequestMapping(value = "/user/checkExistMail", method = RequestMethod.POST)
    public void checkExistMail(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String mail = request.getParameter("mail");
        if (StringUtil.isEmpty(mail)) {
            response.getWriter().write("IllegalArgument");
            return;
        }
        UserInfo userInfo = userService.getByMail(mail.trim());
        if (null == userInfo) {
            response.getWriter().write("false");
        } else {
            response.getWriter().write("true");
        }
    }

}
